package com.jun.admin.core.config;

import cn.hutool.core.thread.RejectPolicy;
import cn.hutool.core.thread.ThreadFactoryBuilder;
import cn.hutool.extra.spring.SpringUtil;
import com.jun.admin.core.mapper.ExecutorTaskInfoMapper;
import com.jun.admin.core.model.ExecutorTaskInfo;
import com.jun.admin.core.model.common.MysqlRunnable;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Queue;
import java.util.concurrent.*;

/**
 * @author yuejun.li
 * @date 2024/8/2 16:51:35
 * 线程池配置
 */
@EnableScheduling
@Configuration
@Slf4j
public class ExectorConfig {

    @Resource
    public MysqlRejectExecutionHandler mysqlRejectExecutionHandler;

    /**
     * 核心线程数 = cpu 核心数 + 1
     */
    private final int core = Runtime.getRuntime().availableProcessors() + 1;

    @Bean("dealThreadExector")
    public ThreadPoolTaskExecutor dealThreadExector(){
        // 创建线程池并设置参数
        ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
        threadPool.setCorePoolSize(core);
        threadPool.setMaxPoolSize(core * 2);
        threadPool.setKeepAliveSeconds(300);
        threadPool.setQueueCapacity(5000);
        threadPool.setThreadNamePrefix("dealThread-");
        threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return threadPool;
    }

    @Bean("scheduleThreadExector")
    public ThreadPoolTaskScheduler scheduleThreadExector(){
        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
        scheduler.setThreadNamePrefix("scheduleThread-");
        scheduler.setPoolSize(20);
        //shutdown\shutdownNow 之后等待3秒
        scheduler.setAwaitTerminationSeconds(60);
        //告诉线程池，在销毁之前执行shutdown方法
        scheduler.setWaitForTasksToCompleteOnShutdown(true);
        return scheduler;
    }

    /**
     * 线程池监控
     * @param executor
     */
    public static void logThreadPoolStatus(ThreadPoolTaskExecutor executor) {
        log.info("ThreadPool Status:");
        log.info("Active Threads: " + executor.getActiveCount());
        log.info("Total Threads: " + executor.getPoolSize());
        log.info("Core Threads: " + executor.getCorePoolSize());
        log.info("Maximum Threads: " + executor.getMaxPoolSize());
        log.info("Task Count: " + executor.getThreadPoolExecutor().getTaskCount());
        log.info("Queue Size: " + executor.getThreadPoolExecutor().getQueue().size());
    }


    @Component
    public static class MysqlRejectExecutionHandler implements RejectedExecutionHandler {

        @Resource
        private ExecutorTaskInfoMapper executorTaskInfoMapper;

        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {

            //将任务持久化到mysql
            if(r instanceof MysqlRunnable){
                MysqlRunnable runnable = (MysqlRunnable) r;
                ExecutorTaskInfo executorTaskInfo = new ExecutorTaskInfo();
                executorTaskInfo.setTaskName(runnable.getTaskName());
                executorTaskInfoMapper.insert(executorTaskInfo);
            }
        }
    }
}